Skip to content

feat: allow block import after NUMBER_OF_COLUMNS / 2 - #8818

Merged
nflaig merged 10 commits into
unstablefrom
cayman/import-after-64-columns
Feb 3, 2026
Merged

feat: allow block import after NUMBER_OF_COLUMNS / 2#8818
nflaig merged 10 commits into
unstablefrom
cayman/import-after-64-columns

Conversation

@wemeetagain

@wemeetagain wemeetagain commented Jan 30, 2026

Copy link
Copy Markdown
Member

Motivation

Description

  • Add condition to blockInput.hasAllData to trigger if the number of columns is enough to reconstruct (gte NUMBER_OF_COLUMNS / 2)
  • Add blockInputColumns.hasComputedAllData, used to await full reconstruction during writeBlockInputToDb

@wemeetagain
wemeetagain requested a review from a team as a code owner January 30, 2026 15:53
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @wemeetagain, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the handling of data columns for blocks requiring erasure coding reconstruction. It optimizes block processing by allowing earlier recognition of data availability once a sufficient number of columns are present, rather than waiting for all. This change is coupled with a more strategic, delayed approach to reconstruction, and a guarantee that all data is fully computed before being committed to storage, improving efficiency and robustness.

Highlights

  • Early Block Availability: Blocks can now be considered available and processed once at least half of the required data columns (NUMBER_OF_COLUMNS / 2) are received, leveraging erasure coding for reconstruction. This allows for earlier block import.
  • Refined Reconstruction Timing: The reconstruction of missing data columns is now consumer-driven and strategically delayed. It is triggered after the attestation cutoff during a slot, which helps desynchronize reconstruction efforts across nodes and reduces immediate processing load.
  • Guaranteed Data Persistence: A new check ensures that all data columns are fully available or successfully reconstructed before a block's data is written to the database, guaranteeing data integrity and completeness upon storage.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1438789730

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/beacon-node/src/chain/blocks/blockInput/blockInput.ts

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a mechanism to allow block import after a certain threshold of data columns are received, enhancing the efficiency of data availability checks. It also adds a consumer-driven delay for reconstruction and sets a reconstruction delay after the attestation cutoff during a slot. The changes involve modifications to ColumnReconstructionTracker.ts, blockInput.ts, writeBlockInputToDb.ts, and gossipHandlers.ts.

Comment thread packages/beacon-node/src/chain/blocks/blockInput/blockInput.ts Outdated
Comment thread packages/beacon-node/src/chain/ColumnReconstructionTracker.ts Outdated
Comment thread packages/beacon-node/src/chain/blocks/writeBlockInputToDb.ts Outdated
Comment thread packages/beacon-node/src/network/processor/gossipHandlers.ts Outdated
Comment thread packages/beacon-node/src/network/processor/gossipHandlers.ts Outdated
@wemeetagain
wemeetagain force-pushed the cayman/import-after-64-columns branch from 1438789 to 796ebef Compare January 30, 2026 16:03
@wemeetagain

Copy link
Copy Markdown
Member Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request implements a performance optimization to allow block import after receiving NUMBER_OF_COLUMNS / 2 data columns, enabling earlier block processing while reconstruction happens in the background. This addresses a performance issue where nodes experienced significant delays in block import due to reconstruction happening during gossip validation.

Changes:

  • Introduces a distinction between hasAllData (enough data to proceed with import, either all sampled columns or ≥ NUMBER_OF_COLUMNS/2 to reconstruct) and hasComputedAllData (all sampled columns actually received)
  • Adds computedDataPromise to track when all sampled columns are available, separate from dataPromise which resolves when enough data exists for reconstruction
  • Updates writeBlockInputToDb to wait for full column reconstruction before persisting to the database

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
packages/beacon-node/src/chain/blocks/blockInput/blockInput.ts Adds hasComputedAllData state tracking, computedDataPromise for delayed reconstruction, and updates hasAllData logic to allow import with ≥ NUMBER_OF_COLUMNS/2 columns
packages/beacon-node/src/chain/blocks/writeBlockInputToDb.ts Adds explicit wait for computed data before DB persistence to ensure all columns are available/reconstructed

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/beacon-node/src/chain/blocks/blockInput/blockInput.ts Outdated
Comment thread packages/beacon-node/src/chain/blocks/blockInput/blockInput.ts
Comment thread packages/beacon-node/src/chain/blocks/blockInput/blockInput.ts
Comment thread packages/beacon-node/src/chain/blocks/blockInput/blockInput.ts Outdated
Comment thread packages/beacon-node/src/chain/blocks/writeBlockInputToDb.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1394e26fb2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/beacon-node/src/chain/blocks/blockInput/blockInput.ts Outdated
@github-actions

github-actions Bot commented Jan 30, 2026

Copy link
Copy Markdown
Contributor

Performance Report

🚀🚀 Significant benchmark improvement detected

Benchmark suite Current: bdf64f9 Previous: 1cab20c Ratio
Set add up to 64 items then delete last 1.8752 us/op 8.1841 us/op 0.23
OrderedSet add up to 64 items then delete last 2.7770 us/op 9.5385 us/op 0.29
Set add up to 64 items then delete middle 1.9276 us/op 5.9827 us/op 0.32
Set add up to 128 items then delete last 3.5227 us/op 12.632 us/op 0.28
Set add up to 128 items then delete middle 3.4967 us/op 11.636 us/op 0.30
Set add up to 256 items then delete first 6.8798 us/op 25.083 us/op 0.27
Set add up to 256 items then delete last 7.3095 us/op 22.146 us/op 0.33
Full benchmark results
Benchmark suite Current: bdf64f9 Previous: 1cab20c Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 949.72 us/op 1.4132 ms/op 0.67
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 32.170 us/op 50.697 us/op 0.63
BLS verify - blst 841.91 us/op 953.78 us/op 0.88
BLS verifyMultipleSignatures 3 - blst 1.2795 ms/op 1.6473 ms/op 0.78
BLS verifyMultipleSignatures 8 - blst 2.0256 ms/op 2.5923 ms/op 0.78
BLS verifyMultipleSignatures 32 - blst 4.3145 ms/op 7.3519 ms/op 0.59
BLS verifyMultipleSignatures 64 - blst 8.1683 ms/op 12.220 ms/op 0.67
BLS verifyMultipleSignatures 128 - blst 15.956 ms/op 20.106 ms/op 0.79
BLS deserializing 10000 signatures 622.54 ms/op 778.26 ms/op 0.80
BLS deserializing 100000 signatures 6.2191 s/op 8.2064 s/op 0.76
BLS verifyMultipleSignatures - same message - 3 - blst 947.57 us/op 1.2846 ms/op 0.74
BLS verifyMultipleSignatures - same message - 8 - blst 1.0738 ms/op 1.2999 ms/op 0.83
BLS verifyMultipleSignatures - same message - 32 - blst 1.7162 ms/op 2.1171 ms/op 0.81
BLS verifyMultipleSignatures - same message - 64 - blst 2.5065 ms/op 3.2440 ms/op 0.77
BLS verifyMultipleSignatures - same message - 128 - blst 4.1242 ms/op 5.3119 ms/op 0.78
BLS aggregatePubkeys 32 - blst 17.530 us/op 23.978 us/op 0.73
BLS aggregatePubkeys 128 - blst 62.206 us/op 85.469 us/op 0.73
getSlashingsAndExits - default max 41.335 us/op 83.241 us/op 0.50
getSlashingsAndExits - 2k 330.97 us/op 345.60 us/op 0.96
isKnown best case - 1 super set check 393.00 ns/op 255.00 ns/op 1.54
isKnown normal case - 2 super set checks 385.00 ns/op 262.00 ns/op 1.47
isKnown worse case - 16 super set checks 388.00 ns/op 242.00 ns/op 1.60
InMemoryCheckpointStateCache - add get delete 2.0690 us/op 2.4730 us/op 0.84
validate api signedAggregateAndProof - struct 1.5531 ms/op 2.4496 ms/op 0.63
validate gossip signedAggregateAndProof - struct 1.4656 ms/op 2.1929 ms/op 0.67
batch validate gossip attestation - vc 640000 - chunk 32 103.69 us/op 181.48 us/op 0.57
batch validate gossip attestation - vc 640000 - chunk 64 89.792 us/op 156.20 us/op 0.57
batch validate gossip attestation - vc 640000 - chunk 128 84.014 us/op 128.21 us/op 0.66
batch validate gossip attestation - vc 640000 - chunk 256 85.926 us/op 114.03 us/op 0.75
bytes32 toHexString 497.00 ns/op 438.00 ns/op 1.13
bytes32 Buffer.toString(hex) 410.00 ns/op 310.00 ns/op 1.32
bytes32 Buffer.toString(hex) from Uint8Array 448.00 ns/op 438.00 ns/op 1.02
bytes32 Buffer.toString(hex) + 0x 389.00 ns/op 320.00 ns/op 1.22
Return object 10000 times 0.22220 ns/op 0.28180 ns/op 0.79
Throw Error 10000 times 3.0973 us/op 5.3965 us/op 0.57
toHex 90.738 ns/op 162.35 ns/op 0.56
Buffer.from 85.051 ns/op 162.82 ns/op 0.52
shared Buffer 57.025 ns/op 104.84 ns/op 0.54
fastMsgIdFn sha256 / 200 bytes 1.6910 us/op 2.3050 us/op 0.73
fastMsgIdFn h32 xxhash / 200 bytes 377.00 ns/op 237.00 ns/op 1.59
fastMsgIdFn h64 xxhash / 200 bytes 421.00 ns/op 319.00 ns/op 1.32
fastMsgIdFn sha256 / 1000 bytes 4.7560 us/op 7.6290 us/op 0.62
fastMsgIdFn h32 xxhash / 1000 bytes 458.00 ns/op 406.00 ns/op 1.13
fastMsgIdFn h64 xxhash / 1000 bytes 498.00 ns/op 377.00 ns/op 1.32
fastMsgIdFn sha256 / 10000 bytes 40.945 us/op 65.582 us/op 0.62
fastMsgIdFn h32 xxhash / 10000 bytes 1.4560 us/op 1.6530 us/op 0.88
fastMsgIdFn h64 xxhash / 10000 bytes 1.0340 us/op 1.1040 us/op 0.94
send data - 1000 256B messages 12.322 ms/op 15.170 ms/op 0.81
send data - 1000 512B messages 12.971 ms/op 19.663 ms/op 0.66
send data - 1000 1024B messages 17.692 ms/op 26.928 ms/op 0.66
send data - 1000 1200B messages 13.706 ms/op 27.589 ms/op 0.50
send data - 1000 2048B messages 13.920 ms/op 27.275 ms/op 0.51
send data - 1000 4096B messages 16.096 ms/op 34.660 ms/op 0.46
send data - 1000 16384B messages 82.153 ms/op 140.20 ms/op 0.59
send data - 1000 65536B messages 240.45 ms/op 323.87 ms/op 0.74
enrSubnets - fastDeserialize 64 bits 1.0240 us/op 1.0950 us/op 0.94
enrSubnets - ssz BitVector 64 bits 497.00 ns/op 476.00 ns/op 1.04
enrSubnets - fastDeserialize 4 bits 319.00 ns/op 177.00 ns/op 1.80
enrSubnets - ssz BitVector 4 bits 504.00 ns/op 415.00 ns/op 1.21
prioritizePeers score -10:0 att 32-0.1 sync 2-0 207.21 us/op 313.03 us/op 0.66
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 258.60 us/op 301.10 us/op 0.86
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 333.69 us/op 544.47 us/op 0.61
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 780.36 us/op 898.61 us/op 0.87
prioritizePeers score 0:0 att 64-1 sync 4-1 684.34 us/op 1.0580 ms/op 0.65
array of 16000 items push then shift 1.2115 us/op 1.8653 us/op 0.65
LinkedList of 16000 items push then shift 7.6870 ns/op 8.8480 ns/op 0.87
array of 16000 items push then pop 65.008 ns/op 93.662 ns/op 0.69
LinkedList of 16000 items push then pop 6.1500 ns/op 8.7660 ns/op 0.70
array of 24000 items push then shift 1.7799 us/op 2.9943 us/op 0.59
LinkedList of 24000 items push then shift 7.2520 ns/op 9.4760 ns/op 0.77
array of 24000 items push then pop 89.723 ns/op 129.25 ns/op 0.69
LinkedList of 24000 items push then pop 6.1320 ns/op 10.449 ns/op 0.59
intersect bitArray bitLen 8 4.6440 ns/op 6.9920 ns/op 0.66
intersect array and set length 8 29.309 ns/op 42.282 ns/op 0.69
intersect bitArray bitLen 128 25.717 ns/op 36.354 ns/op 0.71
intersect array and set length 128 495.96 ns/op 683.07 ns/op 0.73
bitArray.getTrueBitIndexes() bitLen 128 1.3230 us/op 1.3960 us/op 0.95
bitArray.getTrueBitIndexes() bitLen 248 1.9400 us/op 2.4650 us/op 0.79
bitArray.getTrueBitIndexes() bitLen 512 3.7870 us/op 4.6380 us/op 0.82
Full columns - reconstruct all 6 blobs 257.10 us/op 366.02 us/op 0.70
Full columns - reconstruct half of the blobs out of 6 103.01 us/op 127.94 us/op 0.81
Full columns - reconstruct single blob out of 6 28.230 us/op 38.764 us/op 0.73
Half columns - reconstruct all 6 blobs 238.81 ms/op 354.69 ms/op 0.67
Half columns - reconstruct half of the blobs out of 6 119.44 ms/op 200.46 ms/op 0.60
Half columns - reconstruct single blob out of 6 45.541 ms/op 73.076 ms/op 0.62
Full columns - reconstruct all 10 blobs 433.66 us/op 389.11 us/op 1.11
Full columns - reconstruct half of the blobs out of 10 157.69 us/op 192.86 us/op 0.82
Full columns - reconstruct single blob out of 10 27.753 us/op 40.145 us/op 0.69
Half columns - reconstruct all 10 blobs 405.39 ms/op 611.84 ms/op 0.66
Half columns - reconstruct half of the blobs out of 10 210.81 ms/op 397.71 ms/op 0.53
Half columns - reconstruct single blob out of 10 46.425 ms/op 77.521 ms/op 0.60
Full columns - reconstruct all 20 blobs 637.92 us/op 798.08 us/op 0.80
Full columns - reconstruct half of the blobs out of 20 320.85 us/op 384.63 us/op 0.83
Full columns - reconstruct single blob out of 20 28.546 us/op 39.646 us/op 0.72
Half columns - reconstruct all 20 blobs 942.85 ms/op 1.3192 s/op 0.71
Half columns - reconstruct half of the blobs out of 20 478.94 ms/op 937.37 ms/op 0.51
Half columns - reconstruct single blob out of 20 53.770 ms/op 107.82 ms/op 0.50
Set add up to 64 items then delete first 1.8284 us/op 4.2080 us/op 0.43
OrderedSet add up to 64 items then delete first 2.6002 us/op 5.9042 us/op 0.44
Set add up to 64 items then delete last 1.8752 us/op 8.1841 us/op 0.23
OrderedSet add up to 64 items then delete last 2.7770 us/op 9.5385 us/op 0.29
Set add up to 64 items then delete middle 1.9276 us/op 5.9827 us/op 0.32
OrderedSet add up to 64 items then delete middle 4.2971 us/op 10.801 us/op 0.40
Set add up to 128 items then delete first 3.7230 us/op 8.4116 us/op 0.44
OrderedSet add up to 128 items then delete first 5.7213 us/op 13.476 us/op 0.42
Set add up to 128 items then delete last 3.5227 us/op 12.632 us/op 0.28
OrderedSet add up to 128 items then delete last 5.3545 us/op 14.703 us/op 0.36
Set add up to 128 items then delete middle 3.4967 us/op 11.636 us/op 0.30
OrderedSet add up to 128 items then delete middle 11.119 us/op 28.545 us/op 0.39
Set add up to 256 items then delete first 6.8798 us/op 25.083 us/op 0.27
OrderedSet add up to 256 items then delete first 11.121 us/op 30.781 us/op 0.36
Set add up to 256 items then delete last 7.3095 us/op 22.146 us/op 0.33
OrderedSet add up to 256 items then delete last 11.820 us/op 30.299 us/op 0.39
Set add up to 256 items then delete middle 7.2830 us/op 18.513 us/op 0.39
OrderedSet add up to 256 items then delete middle 34.258 us/op 74.163 us/op 0.46
pass gossip attestations to forkchoice per slot 2.1302 ms/op 3.7522 ms/op 0.57
forkChoice updateHead vc 100000 bc 64 eq 0 433.70 us/op 926.60 us/op 0.47
forkChoice updateHead vc 600000 bc 64 eq 0 2.5578 ms/op 5.0168 ms/op 0.51
forkChoice updateHead vc 1000000 bc 64 eq 0 3.7513 ms/op 9.1252 ms/op 0.41
forkChoice updateHead vc 600000 bc 320 eq 0 2.2776 ms/op 6.1687 ms/op 0.37
forkChoice updateHead vc 600000 bc 1200 eq 0 2.2730 ms/op 5.2574 ms/op 0.43
forkChoice updateHead vc 600000 bc 7200 eq 0 3.3368 ms/op 5.2549 ms/op 0.63
forkChoice updateHead vc 600000 bc 64 eq 1000 3.1192 ms/op 5.5481 ms/op 0.56
forkChoice updateHead vc 600000 bc 64 eq 10000 3.2725 ms/op 7.5453 ms/op 0.43
forkChoice updateHead vc 600000 bc 64 eq 300000 7.5830 ms/op 15.573 ms/op 0.49
computeDeltas 1400000 validators 0% inactive 13.167 ms/op 26.603 ms/op 0.49
computeDeltas 1400000 validators 10% inactive 12.219 ms/op 24.198 ms/op 0.50
computeDeltas 1400000 validators 20% inactive 11.038 ms/op 24.006 ms/op 0.46
computeDeltas 1400000 validators 50% inactive 8.3537 ms/op 16.468 ms/op 0.51
computeDeltas 2100000 validators 0% inactive 18.904 ms/op 36.395 ms/op 0.52
computeDeltas 2100000 validators 10% inactive 17.191 ms/op 31.388 ms/op 0.55
computeDeltas 2100000 validators 20% inactive 15.496 ms/op 30.151 ms/op 0.51
computeDeltas 2100000 validators 50% inactive 12.025 ms/op 25.540 ms/op 0.47
altair processAttestation - 250000 vs - 7PWei normalcase 1.6474 ms/op 4.8552 ms/op 0.34
altair processAttestation - 250000 vs - 7PWei worstcase 2.9693 ms/op 6.2374 ms/op 0.48
altair processAttestation - setStatus - 1/6 committees join 91.923 us/op 232.65 us/op 0.40
altair processAttestation - setStatus - 1/3 committees join 180.15 us/op 334.56 us/op 0.54
altair processAttestation - setStatus - 1/2 committees join 260.13 us/op 601.98 us/op 0.43
altair processAttestation - setStatus - 2/3 committees join 348.68 us/op 652.16 us/op 0.53
altair processAttestation - setStatus - 4/5 committees join 498.18 us/op 878.39 us/op 0.57
altair processAttestation - setStatus - 100% committees join 594.91 us/op 1.1083 ms/op 0.54
altair processBlock - 250000 vs - 7PWei normalcase 3.9376 ms/op 5.4062 ms/op 0.73
altair processBlock - 250000 vs - 7PWei normalcase hashState 15.898 ms/op 29.707 ms/op 0.54
altair processBlock - 250000 vs - 7PWei worstcase 24.161 ms/op 40.162 ms/op 0.60
altair processBlock - 250000 vs - 7PWei worstcase hashState 60.291 ms/op 83.931 ms/op 0.72
phase0 processBlock - 250000 vs - 7PWei normalcase 1.8399 ms/op 3.3589 ms/op 0.55
phase0 processBlock - 250000 vs - 7PWei worstcase 20.414 ms/op 42.788 ms/op 0.48
altair processEth1Data - 250000 vs - 7PWei normalcase 286.66 us/op 796.03 us/op 0.36
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:16 7.6780 us/op 10.170 us/op 0.75
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:220 20.581 us/op 42.123 us/op 0.49
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:43 9.7470 us/op 14.910 us/op 0.65
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:19 6.8920 us/op 8.9320 us/op 0.77
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1021 151.96 us/op 199.22 us/op 0.76
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11778 1.3951 ms/op 2.3043 ms/op 0.61
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.8203 ms/op 3.7376 ms/op 0.49
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.8178 ms/op 3.0338 ms/op 0.60
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.8694 ms/op 7.7035 ms/op 0.50
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.0935 ms/op 5.8329 ms/op 0.36
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.5587 ms/op 10.204 ms/op 0.45
Tree 40 250000 create 349.69 ms/op 550.54 ms/op 0.64
Tree 40 250000 get(125000) 113.09 ns/op 182.55 ns/op 0.62
Tree 40 250000 set(125000) 1.0935 us/op 2.1573 us/op 0.51
Tree 40 250000 toArray() 18.837 ms/op 23.757 ms/op 0.79
Tree 40 250000 iterate all - toArray() + loop 18.550 ms/op 28.356 ms/op 0.65
Tree 40 250000 iterate all - get(i) 40.858 ms/op 85.741 ms/op 0.48
Array 250000 create 2.2300 ms/op 3.4194 ms/op 0.65
Array 250000 clone - spread 686.72 us/op 1.0375 ms/op 0.66
Array 250000 get(125000) 0.50100 ns/op 0.53000 ns/op 0.95
Array 250000 set(125000) 0.63900 ns/op 0.53700 ns/op 1.19
Array 250000 iterate all - loop 57.676 us/op 89.896 us/op 0.64
phase0 afterProcessEpoch - 250000 vs - 7PWei 38.775 ms/op 65.097 ms/op 0.60
Array.fill - length 1000000 2.3275 ms/op 4.2968 ms/op 0.54
Array push - length 1000000 8.6454 ms/op 12.904 ms/op 0.67
Array.get 0.20165 ns/op 0.31470 ns/op 0.64
Uint8Array.get 0.21086 ns/op 0.40460 ns/op 0.52
phase0 beforeProcessEpoch - 250000 vs - 7PWei 15.257 ms/op 20.921 ms/op 0.73
altair processEpoch - mainnet_e81889 278.81 ms/op 465.32 ms/op 0.60
mainnet_e81889 - altair beforeProcessEpoch 19.320 ms/op 27.397 ms/op 0.71
mainnet_e81889 - altair processJustificationAndFinalization 6.5170 us/op 8.3750 us/op 0.78
mainnet_e81889 - altair processInactivityUpdates 3.3834 ms/op 6.6773 ms/op 0.51
mainnet_e81889 - altair processRewardsAndPenalties 17.352 ms/op 28.215 ms/op 0.61
mainnet_e81889 - altair processRegistryUpdates 896.00 ns/op 1.0180 us/op 0.88
mainnet_e81889 - altair processSlashings 422.00 ns/op 290.00 ns/op 1.46
mainnet_e81889 - altair processEth1DataReset 427.00 ns/op 300.00 ns/op 1.42
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.2885 ms/op 5.6646 ms/op 0.23
mainnet_e81889 - altair processSlashingsReset 1.3630 us/op 1.4750 us/op 0.92
mainnet_e81889 - altair processRandaoMixesReset 1.2070 us/op 2.0730 us/op 0.58
mainnet_e81889 - altair processHistoricalRootsUpdate 405.00 ns/op 290.00 ns/op 1.40
mainnet_e81889 - altair processParticipationFlagUpdates 848.00 ns/op 987.00 ns/op 0.86
mainnet_e81889 - altair processSyncCommitteeUpdates 376.00 ns/op 236.00 ns/op 1.59
mainnet_e81889 - altair afterProcessEpoch 41.151 ms/op 80.681 ms/op 0.51
capella processEpoch - mainnet_e217614 818.38 ms/op 1.2124 s/op 0.68
mainnet_e217614 - capella beforeProcessEpoch 61.937 ms/op 107.31 ms/op 0.58
mainnet_e217614 - capella processJustificationAndFinalization 5.3870 us/op 10.790 us/op 0.50
mainnet_e217614 - capella processInactivityUpdates 16.599 ms/op 37.212 ms/op 0.45
mainnet_e217614 - capella processRewardsAndPenalties 91.071 ms/op 165.02 ms/op 0.55
mainnet_e217614 - capella processRegistryUpdates 4.7380 us/op 11.212 us/op 0.42
mainnet_e217614 - capella processSlashings 356.00 ns/op 283.00 ns/op 1.26
mainnet_e217614 - capella processEth1DataReset 420.00 ns/op 244.00 ns/op 1.72
mainnet_e217614 - capella processEffectiveBalanceUpdates 14.252 ms/op 23.490 ms/op 0.61
mainnet_e217614 - capella processSlashingsReset 947.00 ns/op 1.2530 us/op 0.76
mainnet_e217614 - capella processRandaoMixesReset 1.2490 us/op 1.7380 us/op 0.72
mainnet_e217614 - capella processHistoricalRootsUpdate 422.00 ns/op 247.00 ns/op 1.71
mainnet_e217614 - capella processParticipationFlagUpdates 787.00 ns/op 877.00 ns/op 0.90
mainnet_e217614 - capella afterProcessEpoch 105.91 ms/op 158.23 ms/op 0.67
phase0 processEpoch - mainnet_e58758 234.05 ms/op 377.28 ms/op 0.62
mainnet_e58758 - phase0 beforeProcessEpoch 65.875 ms/op 90.972 ms/op 0.72
mainnet_e58758 - phase0 processJustificationAndFinalization 5.2930 us/op 11.390 us/op 0.46
mainnet_e58758 - phase0 processRewardsAndPenalties 17.349 ms/op 26.578 ms/op 0.65
mainnet_e58758 - phase0 processRegistryUpdates 3.3000 us/op 4.0390 us/op 0.82
mainnet_e58758 - phase0 processSlashings 422.00 ns/op 235.00 ns/op 1.80
mainnet_e58758 - phase0 processEth1DataReset 392.00 ns/op 396.00 ns/op 0.99
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 790.35 us/op 1.1702 ms/op 0.68
mainnet_e58758 - phase0 processSlashingsReset 1.1860 us/op 1.2660 us/op 0.94
mainnet_e58758 - phase0 processRandaoMixesReset 1.3180 us/op 1.7610 us/op 0.75
mainnet_e58758 - phase0 processHistoricalRootsUpdate 367.00 ns/op 257.00 ns/op 1.43
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.1610 us/op 1.3750 us/op 0.84
mainnet_e58758 - phase0 afterProcessEpoch 32.592 ms/op 56.598 ms/op 0.58
phase0 processEffectiveBalanceUpdates - 250000 normalcase 993.61 us/op 2.7276 ms/op 0.36
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 4.0974 ms/op 4.7438 ms/op 0.86
altair processInactivityUpdates - 250000 normalcase 15.880 ms/op 15.406 ms/op 1.03
altair processInactivityUpdates - 250000 worstcase 13.558 ms/op 20.888 ms/op 0.65
phase0 processRegistryUpdates - 250000 normalcase 4.1340 us/op 9.6310 us/op 0.43
phase0 processRegistryUpdates - 250000 badcase_full_deposits 241.50 us/op 306.00 us/op 0.79
phase0 processRegistryUpdates - 250000 worstcase 0.5 68.300 ms/op 101.23 ms/op 0.67
altair processRewardsAndPenalties - 250000 normalcase 17.524 ms/op 21.181 ms/op 0.83
altair processRewardsAndPenalties - 250000 worstcase 16.053 ms/op 23.997 ms/op 0.67
phase0 getAttestationDeltas - 250000 normalcase 4.8072 ms/op 8.8191 ms/op 0.55
phase0 getAttestationDeltas - 250000 worstcase 4.8602 ms/op 7.3573 ms/op 0.66
phase0 processSlashings - 250000 worstcase 96.408 us/op 109.57 us/op 0.88
altair processSyncCommitteeUpdates - 250000 10.388 ms/op 12.822 ms/op 0.81
BeaconState.hashTreeRoot - No change 395.00 ns/op 277.00 ns/op 1.43
BeaconState.hashTreeRoot - 1 full validator 94.284 us/op 105.60 us/op 0.89
BeaconState.hashTreeRoot - 32 full validator 921.13 us/op 1.2984 ms/op 0.71
BeaconState.hashTreeRoot - 512 full validator 8.3008 ms/op 10.999 ms/op 0.75
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 106.98 us/op 138.57 us/op 0.77
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 1.4552 ms/op 2.0001 ms/op 0.73
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 19.327 ms/op 22.786 ms/op 0.85
BeaconState.hashTreeRoot - 1 balances 79.233 us/op 101.84 us/op 0.78
BeaconState.hashTreeRoot - 32 balances 715.87 us/op 1.0158 ms/op 0.70
BeaconState.hashTreeRoot - 512 balances 6.3801 ms/op 7.8735 ms/op 0.81
BeaconState.hashTreeRoot - 250000 balances 147.52 ms/op 226.41 ms/op 0.65
aggregationBits - 2048 els - zipIndexesInBitList 20.504 us/op 32.257 us/op 0.64
regular array get 100000 times 22.781 us/op 43.705 us/op 0.52
wrappedArray get 100000 times 22.793 us/op 45.453 us/op 0.50
arrayWithProxy get 100000 times 11.432 ms/op 21.795 ms/op 0.52
ssz.Root.equals 20.971 ns/op 35.621 ns/op 0.59
byteArrayEquals 20.564 ns/op 33.233 ns/op 0.62
Buffer.compare 8.8050 ns/op 15.964 ns/op 0.55
processSlot - 1 slots 10.899 us/op 15.833 us/op 0.69
processSlot - 32 slots 2.1202 ms/op 3.7745 ms/op 0.56
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 2.9387 ms/op 6.1317 ms/op 0.48
getCommitteeAssignments - req 1 vs - 250000 vc 1.6047 ms/op 2.7049 ms/op 0.59
getCommitteeAssignments - req 100 vs - 250000 vc 3.2881 ms/op 5.1834 ms/op 0.63
getCommitteeAssignments - req 1000 vs - 250000 vc 3.5660 ms/op 5.4305 ms/op 0.66
findModifiedValidators - 10000 modified validators 706.80 ms/op 794.62 ms/op 0.89
findModifiedValidators - 1000 modified validators 449.02 ms/op 464.20 ms/op 0.97
findModifiedValidators - 100 modified validators 322.07 ms/op 294.00 ms/op 1.10
findModifiedValidators - 10 modified validators 228.45 ms/op 181.64 ms/op 1.26
findModifiedValidators - 1 modified validators 175.47 ms/op 188.02 ms/op 0.93
findModifiedValidators - no difference 205.43 ms/op 199.10 ms/op 1.03
migrate state 1500000 validators, 3400 modified, 2000 new 1.0208 s/op 1.1963 s/op 0.85
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 5.7700 ns/op 5.7300 ns/op 1.01
state getBlockRootAtSlot - 250000 vs - 7PWei 581.43 ns/op 631.42 ns/op 0.92
computeProposerIndex 100000 validators 1.3655 ms/op 2.0209 ms/op 0.68
getNextSyncCommitteeIndices 1000 validators 104.42 ms/op 150.78 ms/op 0.69
getNextSyncCommitteeIndices 10000 validators 102.76 ms/op 151.51 ms/op 0.68
getNextSyncCommitteeIndices 100000 validators 103.44 ms/op 149.02 ms/op 0.69
computeProposers - vc 250000 564.22 us/op 747.68 us/op 0.75
computeEpochShuffling - vc 250000 38.314 ms/op 46.791 ms/op 0.82
getNextSyncCommittee - vc 250000 10.097 ms/op 12.369 ms/op 0.82
nodejs block root to RootHex using toHex 104.20 ns/op 183.37 ns/op 0.57
nodejs block root to RootHex using toRootHex 67.392 ns/op 108.63 ns/op 0.62
nodejs fromHex(blob) 206.67 us/op 411.46 us/op 0.50
nodejs fromHexInto(blob) 622.96 us/op 847.65 us/op 0.73
nodejs block root to RootHex using the deprecated toHexString 492.68 ns/op 657.19 ns/op 0.75
browser block root to RootHex using toHex 255.42 ns/op 338.88 ns/op 0.75
browser block root to RootHex using toRootHex 125.88 ns/op 185.24 ns/op 0.68
browser fromHex(blob) 1.0852 ms/op 1.3468 ms/op 0.81
browser fromHexInto(blob) 597.69 us/op 806.68 us/op 0.74
browser block root to RootHex using the deprecated toHexString 335.43 ns/op 500.31 ns/op 0.67

by benchmarkbot/action

@wemeetagain

Copy link
Copy Markdown
Member Author

Looks like its working
Screenshot from 2026-01-30 12-19-37

@lodekeeper lodekeeper left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall the approach looks good! The separation of hasAllData (enough for reconstruction) vs hasComputedAllData (actually have all sampled columns) makes sense for the performance optimization.

One potential issue I spotted - see inline comment.

Comment thread packages/beacon-node/src/chain/blocks/blockInput/blockInput.ts

@nflaig nflaig left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, leaving up for @twoeths to give this a final pass

@twoeths twoeths left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it works well on hoodi super nodes

Image

import head late is just the same
Image

I was not able to verify validator metrics

@nflaig

nflaig commented Feb 3, 2026

Copy link
Copy Markdown
Member

wrong head vote looks quite a bit better on feat2-super

image

compared to stable-super (other supernodes look similar)

image

@nflaig nflaig added this to the v1.40.0 milestone Feb 3, 2026
@nflaig
nflaig merged commit 2c42f62 into unstable Feb 3, 2026
27 of 31 checks passed
@nflaig
nflaig deleted the cayman/import-after-64-columns branch February 3, 2026 18:01
@codecov

codecov Bot commented Feb 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.36%. Comparing base (63c5c3e) to head (32b89ac).
⚠️ Report is 23 commits behind head on unstable.

Additional details and impacted files
@@            Coverage Diff            @@
##           unstable    #8818   +/-   ##
=========================================
  Coverage     52.36%   52.36%           
=========================================
  Files           848      848           
  Lines         63704    63702    -2     
  Branches       4718     4718           
=========================================
- Hits          33358    33357    -1     
+ Misses        30277    30276    -1     
  Partials         69       69           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@wemeetagain

Copy link
Copy Markdown
Member Author

🎉 This PR is included in v1.40.0 🎉

nflaig pushed a commit that referenced this pull request Mar 9, 2026
… writes (#8974)

**Motivation**

- in preparation for
[gloas](https://github.com/ChainSafe/lodestar/pull/8962/changes#diff-31556a76147b927f6429470ca658ba8ea013b8a869566247b9410f791988454fR32),
columns and block could/should be written separately
- the nice thing of having a `writeDataColumnsToDb()` function is gloas
has to come up with the same interface, and reuse the code, especially
`waitForComputedAllData()` to keep the same functionality we introduced
in [allow block import after 64
columns](#8818)

**Description**

- separate`writeBlockInputToDb()` into `writeBlockAndBlobsToDb()` and
`writeDataColumnsToDb()`
- new `IDataColumnsInput` interface, gloas
[PayloadEnvelopeInput](https://github.com/ChainSafe/lodestar/pull/8962/changes#diff-39f10cf452f670b2fe7018b493ee4c550bb6bf19d0eac2fed0a238ed7511cf36R54)
is expected to implement this cc @ensi321
- only prune `this.serializedCache.clear();` for pre-gloas, need to call
that after we write `PayloadEnvelopeInput` in gloas
- simplify `writeDataColumnsToDb()` to accept a single
`IDataColumnsInput` instead of an array because that's what the consumer
need



**AI Assistance Disclosure**

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Tuyen Nguyen <twoeths@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: NC <17676176+ensi321@users.noreply.github.com>
lodekeeper pushed a commit to lodekeeper/lodestar that referenced this pull request Mar 13, 2026
… writes (ChainSafe#8974)

**Motivation**

- in preparation for
[gloas](https://github.com/ChainSafe/lodestar/pull/8962/changes#diff-31556a76147b927f6429470ca658ba8ea013b8a869566247b9410f791988454fR32),
columns and block could/should be written separately
- the nice thing of having a `writeDataColumnsToDb()` function is gloas
has to come up with the same interface, and reuse the code, especially
`waitForComputedAllData()` to keep the same functionality we introduced
in [allow block import after 64
columns](ChainSafe#8818)

**Description**

- separate`writeBlockInputToDb()` into `writeBlockAndBlobsToDb()` and
`writeDataColumnsToDb()`
- new `IDataColumnsInput` interface, gloas
[PayloadEnvelopeInput](https://github.com/ChainSafe/lodestar/pull/8962/changes#diff-39f10cf452f670b2fe7018b493ee4c550bb6bf19d0eac2fed0a238ed7511cf36R54)
is expected to implement this cc @ensi321
- only prune `this.serializedCache.clear();` for pre-gloas, need to call
that after we write `PayloadEnvelopeInput` in gloas
- simplify `writeDataColumnsToDb()` to accept a single
`IDataColumnsInput` instead of an array because that's what the consumer
need



**AI Assistance Disclosure**

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Tuyen Nguyen <twoeths@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: NC <17676176+ensi321@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[block-input-refactor] potential validateGossipDataColumnSidecar performance issue if node reconstructs columns at the same time

5 participants